<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 14.1.&nbsp;</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-2.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><TD valign="top"><a name="learnphpmysql-CHP-14-SECT-1"></a>
<h3 id="title-IDAM41EF" class="docSection1Title">14.1. </h3>
<p class="docText">Once your code is working, you may be tempted to think that you're done with it. In reality, you may have some security issues that don't affect normal usage but still provide an opening for an attack. The unfortunate reality of web-accessible applications is that they're only as secure as their weakest link. Therefore, you must be conscious of security on every level, from the database to the web server and the PHP processing itself.</p>
<p class="docText">Although you can't make every system truly unbreakable, you can perform the equivalent of dead-bolting doors and locking windows. If you make your system difficult enough to compromise, then it's generally not worth a hacker's effort, though keep in mind that some may still try. We've had our own server locked up from hackers trying to get in, or boatloads of spam that cause the server to belch and stop working temporarily.</p>
<p class="docText">We're going to reiterate some of the security concepts that we discussed while learning the basics of PHP and MySQL. That reduces the risk that you'll build a site without reading about security and so will end up with an easily compromised site. We'll also expand on those topics to give you some more options for making hackers' lives difficult and your life easier.</p>
<a name="learnphpmysql-CHP-14-SECT-1.1"></a>
<h4 id="title-IDAY41EF" class="docSection2Title">14.1.1. Limit Access to Administrative Pages</h4>
<a name="IDX-CHP-14-0631"></a> 
<a name="IDX-CHP-14-0632"></a> 
<a name="IDX-CHP-14-0633"></a> 

<p class="docText">When installing software packages that include a control panel or setup script, you should always either change the script's directory or, in the case of setup scripts, remove them after you're done installing. These scripts can provide a way for a random web surfer to mess up your configuration for the package you installed. While that isn't so bad, in a worst case scenario, it could lead to hackers uploading PHP code of their choice and doing quite unpleasant things with your system. Most web-based packages recommend doing this in their installation instructions. Follow their advice; they wrote the installation manual for a reason: for you to read it! As most technical writers say, "Always published, never read." How many people do you know personally who actually read their alarm clock setup, DVD player setup, or manuals for any number of electronic devices?</p>
<p class="docText">An alternate means of securing directories containing administrative scripts is to create an <span class="docEmphasis">.htaccess</span> file in the same web directory as the scripts. This file tells Apache to require a user to authenticate it before it returns any of the information in that directory.</p>
<p class="docText">To require authentication for a specific directory, place the code in <a class="docLink" href="#learnphpmysql-CHP-14-EX-1">Example 14-1</a> into a file called <span class="docEmphasis">.htaccess</span> in the directory you created for the code.</p>
<a name="learnphpmysql-CHP-14-EX-1"></a><h5 id="title-IDA251EF" class="docExampleTitle">Example 14-1. Using Apache authentication to restrict access to scripts</h5><P><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
AuthType Basic
AuthName "Administrators Only"
AuthUserFile /usr/local/apache/passwd/passwords
Require valid-user
</pre><BR>

</TD></tr></table></P>
<p class="docText">Requesting a directory or subdirectory where this file was saved causes the prompt in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-1">Figure 14-1</a> to display in Firefox; Internet Explorer also displays a similar prompt.</p>
<a name="learnphpmysql-CHP-14-FIG-1"></a><p><center>
<h5 class="docFigureTitle">Figure 14-1. The authentication prompt your browser displays because of the Apache authentication request</H5>
<img border="0" alt="" width="487" height="214" SRC="images/learnphpmysql_1401.jpg">
</center></p><BR>
<p class="docText">Failure to supply a correct username and password causes the warning in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-2">Figure 14-2</a> to display.</p>
<a name="learnphpmysql-CHP-14-FIG-2"></a><p><center>
<H5 class="docFigureTitle">Figure 14-2. The browser won't return any information for a protected directory without a valid login</H5>
<img border="0" alt="" width="549" height="193" SRC="images/learnphpmysql_1402.jpg">
</center></p><BR>
<p class="docText">For best results, this file shouldn't be readable by usersonly by the web server process. On a Unix system, this can be set with the command:</p>
<pre>
chmod 644 /usr/local/apache/passwd/passwords
</pre><br>

<p class="docText">Apache has a special command, the <span class="docEmphasis">htpasswd</span> file, which contains valid usernames and encrypted passwords for your web site. The path to the <span class="docEmphasis">htpasswd</span> file needs to be specified in the <span class="docEmphasis">htaccess</span> file as the <tt>AuthUserFile</tt>.</P>
<p class="docText">As you probably know, usernames and passwords are completely arbitrary; unfortunately, there's no correspondence between the usernames and passwords used in your <span class="docEmphasis">htaccess</span> file. For example, if your login name is <tt>mdavis</tt>, your username for the <span class="docEmphasis">htaccess</span> file could also be <tt>mdavis</tt>, or it could be <tt>Michele</tt>.</P>
<p><table border="0" bgcolor="black" cellspacing="0" cellpadding="1" width="90%" align="center"><tr><td><table bgcolor="white" width="100%" border="0" cellspacing="0" cellpadding="6"><tr><TD width="60" valign="top"><img src="images/tip_yellow.jpg" width="50" height="54" alt=""></td><TD valign="top">
<p class="docText">Keep in mind that you need to set up usernames that are understandable for your site, and then you need to create passwords for those usernames.</p>
</td></TR></table></TD></tr></table></P><br>
<p class="docText">It's important to know that the <tt>htpasswd</tt> command is used to create the username and password pairs. The full path for the command on a Unix/Linux server is <span class="docEmphasis">/usr/local/bin/htpasswd</span>. Remember, the <tt>htpasswd</tt> command reflexively encrypts every single password before writing it to the <span class="docEmphasis">htpasswd</span> file. In other words, the <tt>htpasswd</tt> command takes the name of the password file and the username to set its parameters. Look at <a class="docLink" href="#learnphpmysql-CHP-14-EX-2">Example 14-2</a> for the correct format.</p>
<a name="learnphpmysql-CHP-14-EX-2"></a><h5 id="title-IDAFD2EF" class="docExampleTitle">Example 14-2. Creating an Apache password for .htaccess</h5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
htpasswd -c /usr/local/apache/passwd/passwords mdavis
</pre><br>

</td></tr></table></p>
<p class="docText">The <tt>-c</tt> option is required only for adding the first entry to a password file. You'll be prompted to enter the password twice to ensure that you don't have a typo. If the passwords match, you'll see the following:</p>
<pre>
   Adding password for user mdavis
</pre><BR>

<p class="docText">As stated above, keep in mind that if the password is valid, it's automatically encrypted. When you do this, only users who respond correctly to the authentication prompt are able to access pages in the directory in which <span class="docEmphasis">.htaccess</span> resides in any subdirectories.</p>
<p><table border="0" bgcolor="black" cellspacing="0" cellpadding="1" width="90%" align="center"><TR><TD><table bgcolor="white" width="100%" border="0" cellspacing="0" cellpadding="6"><tr><TD width="60" valign="top"><img src="images/tip_yellow.jpg" width="50" height="54" alt=""></td><td valign="top">
<p class="docText">On Windows, the procedure is quite similar, but instead of using <span class="docEmphasis">htpasswd</span>, use <span class="docEmphasis">htpasswd.exe</span>. It's usually located in <span class="docEmphasis">C:\Program File\Apache Group\Apache2\bin\</span>. You can also place the <span class="docEmphasis">.htpasswd</span> file in the <span class="docEmphasis">C:\Program Files\Apache Group\Apache2</span> directory.</p>
</TD></tr></table></TD></tr></table></p><BR>

<a name="learnphpmysql-CHP-14-SECT-1.2"></a>
<H4 id="title-IDANE2EF" class="docSection2Title">14.1.2. Including Files</h4>
<p class="docText">Because no one ever wants to recreate the wheel, there are ways to reuse code. It probably sounds like plagiarism, but in the world of open source, it's a bonus to reuse code using include files.<a name="IDX-CHP-14-0634"></a> 
<a name="IDX-CHP-14-0635"></a> 
<a name="IDX-CHP-14-0636"></a> 
</P>
<p class="docText">Obviously, the ability to reuse code by including makes your life easier by not having the same blocks of code repeated over and over in your programs. It also improves the maintainability of your pages, because code used on multiple pages need only be modified once in the PHP source file.</p>
<p class="docText">The downside to look out for is using filenames for your included code that allows the web server to return the contents of the file without being processed by PHP. This has two major security risks. First, it allows a user to see your PHP source code, which could allow someone to look for weaknesses in the code and then know how to easily exploit them. Second, you could expose passwords that may be stored in an <span class="docEmphasis">include</span> file. In order to thwart these problems, make sure that you always name your included file with the <span class="docEmphasis">.php</span> extension and not something such as <span class="docEmphasis">.inc</span> that won't be processed if viewed directly. But, there is a caveat when using <tt>include</tt>.</p>
<p class="docText">For PHP versions before 4.0.2, <tt>require</tt> always attempts to read the target file, even if the line it's on never executes. The good news is that the conditional statement won't affect the <tt>require</tt> statement. Then again, if the line on which <tt>require</tt> occurs doesn't execute, neither will any of the code in the target file. Additionally, looping structures don't affect the operation of the <tt>require</tt> statement. Remember that the code in the target file is still subject to the loop, even though the <tt>require</tt> statement occurs only once.</P>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-FIG-3">Figure 14-3</a> shows what can happen by simply requesting your <span class="docEmphasis">db_login.php</span> script if it ends in an <span class="docEmphasis">.inc</span> extensionfor example, <a class="docLink" target="_blank" href="http://10.0.0.1/db_login.inc">http://10.0.0.1/db_login.inc</a>.</P>
<a name="learnphpmysql-CHP-14-FIG-3"></a><p><center>
<h5 class="docFigureTitle">Figure 14-3. Nothing that we want the world to see!</h5>
<img border="0" alt="" width="549" height="175" SRC="images/learnphpmysql_1403.jpg">
</center></p><BR>
<p class="docText">You should avoid ending the login script with a <span class="docEmphasis">.inc</span> extension; there's a better way. The files should be renamed with a <span class="docEmphasis">.php</span> extension. You can put your include files that have sensitive information in a directory that's not under the published web root. Another good way is to place it in a directory that's protected by an <span class="docEmphasis">.htaccess</span> file, at the very least.</p>

<a name="learnphpmysql-CHP-14-SECT-1.3"></a>
<H4 id="title-IDADH2EF" class="docSection2Title">14.1.3. Storing Passwords in the Database</h4>
<a name="IDX-CHP-14-0637"></a> 
<a name="IDX-CHP-14-0638"></a> 
<a name="IDX-CHP-14-0639"></a> 
<a name="IDX-CHP-14-0640"></a> 
<a name="IDX-CHP-14-0641"></a> 
<a name="IDX-CHP-14-0642"></a> 
<a name="IDX-CHP-14-0643"></a> 

<p class="docText">In general, it's never a good idea to store passwords for users in the database without encoding them. The principal reason for this is that if someone is able to gain access to your database, even just read-only access, he can get all of your users' passwords. This allows that person to log in as other users, and he could attempt to use the same password on other web sites, since many users use common passwords across numerous sites.</p>
<p class="docText">We see password violation on a weekly basis. Our teenager uses instant messaging, and his friends know what he likes and he knows what they like, so all the teens can extrapolate someone's password just based on their knowledge of their friends. Then they can log in as someone else and raise havoc by pretending to be <tt>soccergrrl</tt>, as opposed to their own login, <tt>randomkid</tt>.</P>
<p class="docText">There are only a few downsides to encrypting passwords, including slightly increased complexity and the need to change a password for a user instead of being able to relay the forgotten password. One way to work around this problem is to store a password hint in the database. This is something that a user can enter when registering that'll help her remember what password she used. For example, if your password is your dog's name, you might use "dog" as a reminder.</P>
<p class="docText">So far, we've only discussed a single way to encrypt a password using the <tt>md5</tt> one-way encrypt function. There's actually another function that can be used that is more secure. It's called <tt>sha1</tt>, which stands for <span class="docEmphasis">secure hash algorithm</span>. Instead of returning a 128-bit string such as <tt>md5, sha1</tt> returns a 160-bit string. The added length helps make it harder to guess the original password value. Additionally, the algorithm that's used in <tt>sha1</tt> is more advanced that <tt>md5</tt>, making it more difficult to break the code.</p>
<p class="docText">For example, try <a class="docLink" href="#learnphpmysql-CHP-14-EX-3">Example 14-3</a> and see what you get when you run the code.</P>
<a name="learnphpmysql-CHP-14-EX-3"></a><h5 id="title-IDAOJ2EF" class="docExampleTitle">Example 14-3. Comparing the output of md5 to that of sha1</h5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
&lt;?php
echo "Encrypting &lt;b&gt;testing&lt;/b&gt; using md5: ".md5("testing");
echo "&lt;br /&gt;";
echo "Encrypting &lt;b&gt;testing&lt;/b&gt; using sha1: ".sha1("testing");
?&gt;
</pre><br>

</td></tr></table></p>
<p class="docText">This displays the result shown in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-4">Figure 14-4</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-4"></a><p><center>
<h5 class="docFigureTitle">Figure 14-4. The output from sha1 is slightly longer than md5's</H5>
<img border="0" alt="" width="549" height="162" SRC="images/learnphpmysql_1404.jpg">
</center></p><br>

<a name="learnphpmysql-CHP-14-SECT-1.4"></a>
<H4 id="title-IDAMK2EF" class="docSection2Title">14.1.4. The Problem with Automatic Global Variables</H4>
<p class="docText">Sometimes making life easy for developers can cause problems. Early versions of PHP (before version 4.2.0) by default allowed you to access variables for a <tt>GET</tt> or
<tt>POST</tt> operation automatically as global variables with the name of variable coming from whatever came from the <tt>GET</tt> or <tt>POST</tt> operation. While this was very convenient, it also created a big security hole.</p>
<P><table border="0" bgcolor="black" cellspacing="0" cellpadding="1" width="90%" align="center"><tr><td><table bgcolor="white" width="100%" border="0" cellspacing="0" cellpadding="6"><tr><TD width="60" valign="top"><img src="images/tip_yellow.jpg" width="50" height="54" alt=""></td><TD valign="top">
<p class="docText">The actual setting that changed its default value is called <tt>register_globals</tt>. It could be set to <tt>OFF</tt> in the <span class="docEmphasis">php.ini</span> configuration file before. Most people didn't change the default value though.</p>
</td></TR></table></TD></tr></table></P><br>
<p class="docText">It wasn't really that <tt>register_globals</tt> was a terrible idea, it's just that most people didn't properly check the source of a variable before use. The danger was that because PHP doesn't require variables to be predefined, it's possible for a malicious user to call your PHP script with a <tt>GET</tt> or <tt>POST</tt> parameter that you aren't anticipating. If that variable matches the name of a variable that you're using for something important, such as indicating whether a password matches, then the malicious user might be able to change the functionality of your program just by adding a false parameter.</p>
<p class="docText">Unfortunately, admitting that this was a mistake and having to change the default value wasn't without some pain. Because many people assumed that they could automatically reference form-submitted values as globals, scripts that used to work now find no value where they expect it. Code had to be rewritten, and worse yet, you may still find some code that hasn't been fixed and therefore doesn't work and won't even tell you the problem.</P>
<P><table border="0" bgcolor="black" cellspacing="0" cellpadding="1" width="90%" align="center"><tr><td><table bgcolor="white" width="100%" border="0" cellspacing="0" cellpadding="6"><tr><td width="60" valign="top"><img src="images/warning_yellow.jpg" width="51" height="36" alt=""></TD><td valign="top">
<p class="docText">If you've just downloaded a set of PHP scripts from the Internet and find that they run but essentially ignore form-inputted data, there's a good chance that they were written with the assumption that <tt>register_globals</tt> was on. You'll need to either expand out the variables or change the references within the scripts to the appropriate <tt>$_GET</tt> or <tt>$_POST</tt> superglobals.</P>
</td></tr></table></TD></TR></table></p><BR>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-EX-4">Example 14-4</a> shows how the globals could be misused (assuming the function <tt>check_username_and_password</tt> is defined already).</p>
<a name="learnphpmysql-CHP-14-EX-4"></a><h5 id="title-IDANM2EF" class="docExampleTitle">Example 14-4. Not initializing a variable was a hole in sample.php</h5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
&lt;?php
if (check_username_and_password()) {
   //they logged in successfully
   $access = TRUE;
}
if ($access) {
   echo "Welcome to the administrative control panel.";
   //more privileged code here...
}
else {
  echo "Access denied";
}
?&gt;
</pre><br>

</td></tr></table></p>
<p class="docText">What should have happened in the code for <a class="docLink" href="#learnphpmysql-CHP-14-EX-4">Example 14-4</a> is to set <tt>$access</tt> to <tt>FALSE</tt> before it was used. Had a malicious user called a script such as <a class="docLink" target="_blank" href="http://sample.php?access=1">http://sample.php?access=1</a>, she'd see <a class="docLink" href="#learnphpmysql-CHP-14-FIG-5">Figure 14-5</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-5"></a><p><center>
<H5 class="docFigureTitle">Figure 14-5. A security breach</h5>
<img border="0" alt="" width="549" height="169" SRC="images/learnphpmysql_1405.jpg">
</center></p><BR>
<p class="docText">The value for <tt>$access</tt> of <tt>TRUE</tt> from the <tt>GET</tt> parameter would cause the check for access to return <tt>trUE</tt> when <tt>register_globals</tt> is on. Modifying the code to look like this:</P>
<pre>
&lt;?php
//predefining the value is good coding practice anyway
$access = FALSE;
if (check_username_and_password()) {
   //they logged in successfully
   $access = TRUE;
}
if ($access) {
   echo "Welcome to the administrative control panel.";
   //more privileged code here...
}
else {
  echo "Access denied";
}
?&gt;
</pre><br>

<p class="docText">causes the correct message to come up, as shown in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-6">Figure 14-6</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-6"></a><p><center>
<H5 class="docFigureTitle">Figure 14-6. Access is correctly denied regardless of the register_globals setting</h5>
<img border="0" alt="" width="549" height="169" SRC="images/learnphpmysql_1406.jpg">
</center></P><br>
<p class="docText">The legacy of <tt>register_globals</tt> doesn't stop with data supplied from forms. It's possible to read session variables when <tt>register_globals</tt> is on. In <a class="docLink" href="#learnphpmysql-CHP-14-EX-5">Example 14-5</a>, <tt>$username</tt> could also come from other sources, such as <tt>GET</tt>, which is part of the URL request.</p>
<a name="learnphpmysql-CHP-14-EX-5"></a><H5 id="title-IDAKP2EF" class="docExampleTitle">Example 14-5. Sessions with register_globals on or off in session_test.php</H5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><TR><td>

<pre>
&lt;?php
session_start();
if (isset($username)) {
  echo "Hello $username";
} else {
  echo "Please login.";
}
?&gt;
</pre><br>

</TD></TR></table></p>
<p class="docText">Requesting <a class="docLink" target="_blank" href="http://10.0.0.1/session_test.php?username=">http://10.0.0.1/session_test.php?username=</a>"<span class="docEmphasis">test"</span> with <tt>register_globals</tt> on returns what is shown in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-7">Figure 14-7</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-7"></a><p><center>
<h5 class="docFigureTitle">Figure 14-7. Any security has been effectively circumvented</H5>
<img border="0" alt="" width="549" height="158" SRC="images/learnphpmysql_1407.jpg">
</center></p><BR>
<p class="docText">The correct way is to access the variable from the <tt>$_SESSION</tt> super global, as in <a class="docLink" href="#learnphpmysql-CHP-14-EX-6">Example 14-6</a>.</p>
<a name="learnphpmysql-CHP-14-EX-6"></a><h5 id="title-IDA2Q2EF" class="docExampleTitle">Example 14-6. Session using the proper $_SESSION super global</H5><P><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><TD>

<pre>
&lt;?php
session_start();
$username=$_SESSION['username'];
if (isset($username)) {
  echo "Hello $username";
} else {
  echo "Please login.";
}
?&gt;
</pre><br>

</td></tr></table></p>
<p class="docText">The code in <a class="docLink" href="#learnphpmysql-CHP-14-EX-6">Example 14-6</a> returns <a class="docLink" href="#learnphpmysql-CHP-14-FIG-8">Figure 14-8</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-8"></a><p><center>
<h5 class="docFigureTitle">Figure 14-8. Users must log in and cannot bypass the login with a global variable</h5>
<img border="0" alt="" width="549" height="158" SRC="images/learnphpmysql_1408.jpg">
</center></p><br>
<p class="docText">To continue to access a user-supplied variable without caring about where it came from, you can use the <tt>$_REQUEST</tt> superglobal, as shown in <a class="docLink" href="#learnphpmysql-CHP-14-EX-7">Example 14-7</a>.</p>
<a name="learnphpmysql-CHP-14-EX-7"></a><h5 id="title-IDAIS2EF" class="docExampleTitle">Example 14-7. Detecting simple variable poisoning</H5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><TD>

<pre>
&lt;?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {
   // MAGIC_COOKIE comes from a cookie.
   // Be sure to validate the cookie data!
} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {
   mail("admin@example.com", "Possible breakin attempt", $_SERVER['REMOTE_ADDR']);
   echo "Security violation, admin has been alerted.";
   exit;
} else {
   // MAGIC_COOKIE isn't set through this REQUEST

}
?&gt;
</pre><BR>

</td></TR></table></p>
<p class="docText">While <tt>register_globals</tt> is turned off by default to improve security, it doesn't mean that the problem of validating has gone away.</p>
<p class="docText">Remember to always initialize variables. This simple step can thwart a malicious attempt to send data through an alternate source. It also helps the readability of your code at almost no cost.</p>
<P><table border="0" bgcolor="black" cellspacing="0" cellpadding="1" width="90%" align="center"><tr><TD><table bgcolor="white" width="100%" border="0" cellspacing="0" cellpadding="6"><tr><td width="60" valign="top"><img src="images/tip_yellow.jpg" width="50" height="54" alt=""></TD><TD valign="top">
<p class="docText">Superglobal arrays such as <tt>$_GET, $_POST</tt>, and <tt>$_SERVER</tt> have been available since PHP 4.1.0.</p>
</TD></tr></table></td></TR></table></P><br>


<a href="11011536.html"><img src="images/pixel.jpg" alt="" width="1" height="1" border="0"></a></TD></TR></table>
<br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-2.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<script type="text/javascript"><!--
google_ad_client = "pub-0203281046321155";
google_alternate_ad_url = "http://www.bookhtml.com/adbrite.htm";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="4867465545";
google_color_border = "FFFFFF";
google_color_link = "0000FF";
google_color_bg = "FFFFFF";
google_color_text = "000000";
google_color_url = "0000FF";
//--></script>
<script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</html>
